import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qfedu.anon.DeptMapper;
import com.qfedu.pojo.Dept;
import com.qfedu.pojo.Employee;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class MybatisTest {

    Reader reader = null;
    SqlSession session = null;
    SqlSessionFactory sessionFactory=null;

    @Before //@Before：在测试方法执行之前执行
    public void open() {
        try {
            reader = Resources.getResourceAsReader("mabatis-config.xml");
            sessionFactory = new SqlSessionFactoryBuilder().build(reader);
            session = sessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After  //@After: 在测试方法执行之后去执行
    public void close() {
        session.close();
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void insert() {

        try {
            //session.insert("DEPT.addDept","技术部5"); //传个参数//每一个xml文件的mapper有一个唯一的namespce(如DEPT),方法有一个唯一的id(如addDept)
            Dept dept = new Dept();
            dept.setName("安保部门");
            session.insert("DEPT.insertDept", dept); //传对象
            session.commit(); //提交事务
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback(); //事务回滚
        }


    }

    @Test
    public void insertEmployee() {


        try {
            //使用MyBatis提供的Resources类加载mybatis的配置文件
            // reader = Resources.getResourceAsReader("mabatis-config.xml");
            //构建sqlSession的工厂
            //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
            //创建能执行映射文件中sql的sqlSession
            // session = sessionFactory.openSession();
            //创建实体对象，将它insert到数据库中
            Employee emp = new Employee();
            emp.setName("小红3");
            emp.setHireDate(new Date());
            // emp.setDeptId(1);
            emp.setSalary(10101F);

            //使用session的insert方法执行添加操作
            //第一个参数是要Mapper文件的namespace+.+语句的id
            //第二个参数的类型要和语句的parameterType一致
            session.insert("EMPLOYEE.addEmp", emp); //传对象
            session.commit(); //提交事务
            //insert标签中设置keyProperty和useGeneratedKeys后才能看到值，否则是null
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback(); //事务回滚
        }
    }

    @Test
    public void testUpdate() {
        try {
//            Dept dept= new Dept();
//            dept.setId(1);
//            dept.setName("运营部");
//            session.update("DEPT.updateDept",dept);
            Employee emp = new Employee();
            emp.setName("李四");
            emp.setHireDate(new Date());
            //emp.setDeptId(1);
            emp.setSalary(12101F);
            emp.setId(2);
            session.update("EMPLOYEE.updateEmp", emp);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }
    }

    @Test
    public void testDelete() {
        try {
            session.delete("DEPT.deleteDept", 17);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
        }
    }

    @Test
    public void testSelect() { //查询不需要提交事务
      /*  List<Dept> depts=session.selectList("DEPT.getDeptList");
        for(Dept dept:depts){
            System.out.println(dept);
        }*/

        //List<Employee> emps=session.selectList("EMPLOYEE.getEmpList");
        List<Employee> emps = session.selectList("EMPLOYEE.getEmpList");
        for (Employee emp : emps) {
            System.out.println(emp);
        }
    }


    @Test
    public void getDeptWithEmp() {
        List<Dept> deptList = session.selectList("DEPT.getDeptWithEmp");
        for (Dept dept : deptList) {
            System.out.println(dept.getName());
            if (dept.getName() != null) {
                for (Employee emp : dept.getEmps()) {
                    System.out.println(emp);
                }
            }
            System.out.println("============================");
        }
    }

    @Test
    public void testSQL() {
        Employee employee = new Employee();
        employee.setName("李四");
        //employee.setSalary(100001F);
        //employee.setId(2);
        List<Employee> employees = session.selectList("EMPLOYEE.getParam", "salary");
        for (Employee emp : employees) {
            System.out.println(emp);
        }
        //session.selectList("EMPLOYEE.getEmpList",employee);
        //session.update("EMPLOYEE.updateEmp",employee);

   /* List<Integer> list=new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    session.selectList("EMPLOYEE.getEmployeeByIds",list);
*/
    }

    @Test
    public void testPage() {
        PageHelper.startPage(1, 2, "id desc");
        List<Dept> deptList = session.selectList("DEPT.getDeptList");
        PageInfo<Dept> pageInfo = new PageInfo<>(deptList);
        System.out.println("页码：" + Arrays.toString(pageInfo.getNavigatepageNums()));
        System.out.println("当前页码：" + pageInfo.getPageNum());
        System.out.println("每页几条：" + pageInfo.getPageSize());
        System.out.println("总页数：" + pageInfo.getPages());
        System.out.println("有没有上一页：" + pageInfo.isHasPreviousPage());
        System.out.println("有没有下一页:" + pageInfo.isHasNextPage());
        for (Dept dept : deptList) {
            System.out.println(dept);
        }
    }

//==================================注解的方式对数据库操作========
    @Test  //注解的方式（操作有限，不如xml文件）
    public void testAdd() {
        DeptMapper deptMapper = session.getMapper(DeptMapper.class); // mabatis-config.xml中说明了
        Dept dept = new Dept();
        dept.setName("注解方式");
        deptMapper.addDept(dept);  //添加
        session.commit();

        dept.setId(2);
        deptMapper.updateDept(dept);  //修改
        session.commit();

         deptMapper.delete(4);  //删除
         session.commit();

        List<Dept> deptList = deptMapper.getDeptList();
        for (Dept dep : deptList) {
            System.out.println(dep);
        }
    }

//============================================================================

    //同一个SqlSession中，执行了任何一个update()、insert()、delete()或commit()后都会清空一级缓存。


    @Test
    public void testCache(){
        DeptMapper deptMapper= session.getMapper(DeptMapper.class);
        List<Dept> deptList1=deptMapper.getDeptList();  //session把同样结果集的数据进行了缓存(控制台只执行了一次sql语句)
        List<Dept> deptList2=deptMapper.getDeptList();
        deptMapper.getDepById(1);
        deptMapper.getDepById(1);
    }

    /**
     * 二级缓存需要用户去设置。二级缓存比一级缓存范围更大，一级缓存是一个SqlSession范围内的，
     * 不同的SqlSession之间不共享。而二级缓存可以实现多个SqlSession之间共享对同一个Mapper的缓存。
     */
    @Test
    public void testSecondCache(){
        Dept dept1 = session.selectOne("DEPT.getDeptById",14);
       session.close(); ////关闭session1，此时将dept1写入二级缓存(不关闭session可能修改数据库数据，二级缓存写入的数据就不对了)
      SqlSession session2=sessionFactory.openSession();
        Dept dept2=session2.selectOne("DEPT.getDeptById",14);
    }


    /**     第三方缓存
     * ehcache缓存数据可以在内存和磁盘上缓存数据，无需担心容量问题。
     * Mybatis与ehcache结合使用，可以实现多个SqlSession对同一个Mapper的缓存共享。
     */
    @Test
    public void testThirdCache(){
        List<Dept> deptList=session.selectList("DEPT.getDeptList");
        Dept dept=session.selectOne("DEPT.getDeptById");
        session.close();
        CacheManager cacheManager=CacheManager.getInstance();
        if(cacheManager.cacheExists("DEPT")){
            Cache cache=cacheManager.getCache("DEPT");
            System.out.println("存放数据的文件名："+cache.getKeys());
        }

        SqlSession session1 = sessionFactory.openSession();
        List<Dept> deptList1=session1.selectList("DEPT.getDeptList");
        System.out.println(deptList1);
    }
}
